package ink.metoo.gude.module.websocket.handler

import ink.metoo.gude.model.TopicConst
import ink.metoo.gude.module.security.util.simpleUserDetails
import ink.metoo.gude.module.websocket.domain.ToPublicType
import ink.metoo.gude.module.websocket.domain.UserChangeStatus
import ink.metoo.gude.module.websocket.service.SessionNoticeService
import ink.metoo.gude.module.websocket.util.asStompHeaderAccessor
import org.springframework.context.event.EventListener
import org.springframework.stereotype.Component
import org.springframework.web.socket.messaging.SessionDisconnectEvent
import org.springframework.web.socket.messaging.SessionSubscribeEvent
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit

@Component
class WebSocketEventHandler(private val sessionNoticeService: SessionNoticeService) {

    private val scheduler: ScheduledExecutorService = Executors.newScheduledThreadPool(128)

    @EventListener
    fun onSubscribe(event: SessionSubscribeEvent) {
        val accessor = event.message.asStompHeaderAccessor()
        val sessionId = accessor.sessionId!!

        // 延迟处理一秒防止丢失
        scheduler.schedule({
            when (accessor.destination) {
                TopicConst.PUBLIC_TOPIC -> {
                    sessionNoticeService.sendUserStatusChangeNotice(
                        sessionId, event.user.simpleUserDetails, ToPublicType.USER_STATUS_CHANGE,
                        UserChangeStatus.JOIN
                    )
                }

                TopicConst.PRIVATE_USER_SUBSCRIBE_TOPIC -> {
                    sessionNoticeService.sendConnectStatistics(sessionId, event.user.simpleUserDetails)
                }
            }
        }, 1L, TimeUnit.SECONDS)
    }


    @EventListener
    fun onDisconnect(event: SessionDisconnectEvent) {
        val accessor = event.message.asStompHeaderAccessor()
        val sessionId = accessor.sessionId!!
        sessionNoticeService.sendUserStatusChangeNotice(
            sessionId, event.user.simpleUserDetails, ToPublicType.USER_STATUS_CHANGE,
            UserChangeStatus.LEAVE
        )
    }


}